#encoding=utf8
'''
Created on Sep 12, 2014

@author: jingyang <jingyang@smalltreemedia.com>
'''
import json
import urllib

from django import forms
from django.db.models.query_utils import Q
from django.contrib.auth.models import User, Permission, Group

from app_info.models import App, SUPPORTED_DEVICES, Studio, StudioCloud,\
    SPECIAL_SETTINGS, APP_STORE, AppVersion, PURPOSE, YES_OR_NO,\
    FlurryKey, AppleID, GAKey, UserGroup, QuantCastKey, Company, ProductionTeam
import settings
from core.widgets import CustomCheckboxSelectMultiple, CustomTextarea,\
    CustomFilteredSelectMultiple
from django.contrib.admin.widgets import FilteredSelectMultiple
from utils import api_call
from sdk_info.models import SDKVersion


class AppForm(forms.ModelForm):
    error_msg = {'server_error': u'''Oops...There is something wrong with the
                    server.Pls let the backend programmer know this message
                    immediately.''',
                 'exist': u'''Oops...%s exists in Central Services. Pls choose
                    another one.''',
                 'invalid_characters': u'''This field contains invalid characters. Maybe it's Chinese character?'''}

    supported_devices = forms.MultipleChoiceField(required=False,
        widget=CustomCheckboxSelectMultiple, choices=SUPPORTED_DEVICES)
    store_link = forms.CharField(required=False, max_length=200, widget=CustomTextarea)
#    flurry_key = forms.CharField(required=False, max_length=100, label=u'Flurry Key')
    media_local = forms.CharField(required=False, max_length=1000,
        label=u'Product Submission Doc (Local)', widget=CustomTextarea)
    media_remote = forms.CharField(required=False, max_length=1000,
        label=u'Product Submission Doc (Dropbox)', widget=CustomTextarea)
    display_name = forms.CharField(required=False, max_length=200,
        label=u'Display Name on Device')
    special = forms.MultipleChoiceField(required=False,
        widget=CustomCheckboxSelectMultiple, choices=SPECIAL_SETTINGS,
        label=u'Special Settings')

    company = forms.ModelChoiceField(required=True, queryset=Company.objects.all())
#    cross_local = forms.CharField(required=False, max_length=1000,
#        label=u'Cross Promo Creatives (Local)', widget=CustomTextarea)
#    cross_remote = forms.CharField(required=False, max_length=1000,
#        label=u'Cross Promo Creatives (Dropbox)', widget=CustomTextarea)
#    orientation = forms.CharField(required=False, max_length=1,
#        label=u'Orientation', widget=forms.Select(choices=ORIENTATION))

    def __init__(self, *args, **kwargs):
        super(AppForm, self).__init__(*args, **kwargs)
        extra = self.instance.appextrainfo if hasattr(self.instance, 'appextrainfo') else None
        if extra:
#            self.fields['flurry_key'].initial = extra.flurry_key
            self.fields['media_local'].initial = extra.media_local
            self.fields['media_remote'].initial = extra.media_remote
            self.fields['display_name'].initial = extra.display_name
            self.fields['special'].initial = extra.special
#            self.fields['cross_local'].initial = extra.cross_local
#            self.fields['cross_remote'].initial = extra.cross_remote
#            self.fields['orientation'].initial = extra.orientation
        if self.instance.status == 'V':
#            self.fields['flurry_key'].required = True
            self.fields['media_local'].required = True
            self.fields['media_remote'].required = True
            self.fields['display_name'].required = True

        # # company default setup
        # self.fields['company'].queryset = Company.objects.all()
        # self.fields['company'].initial = Company.objects.filter(pk=self.instance.pk)

    class Meta:
        model = App

#    def clean(self):
#        print '--->', self._errors
#        return self.cleaned_data

    def clean_special(self):
        special = self.cleaned_data.get('special')
        self.instance.special = str(special) if special else None
        return special

    def clean_prj_code(self):
        prj_code = self.cleaned_data.get('prj_code').strip()
        if 'prj_code' in self.changed_data:
            if prj_code:
                if "XXX" in prj_code:
                    raise forms.ValidationError("Replace XXX to number")
                try:
                    res = urllib.urlopen('%s%s/?t=code' % (settings.CHECK_URL, prj_code))
                    rtn = res.read()
                    rtn = json.loads(rtn)
                except Exception, e:
                    raise forms.ValidationError(self.error_msg['server_error'])
                if rtn.get('exist'):
                    raise forms.ValidationError(self.error_msg['exist'] % 'App code')
        return prj_code

    def clean_bundle_id_suffix(self):
        bundle_id_suffix = self.cleaned_data.get('bundle_id_suffix', '').strip().replace(" ", "")
        if 'bundle_id_suffix' in self.changed_data:
            if bundle_id_suffix:
                if self.cleaned_data.get('platform') == 'A':
                    bundle_id_suffix = bundle_id_suffix.replace('-', '_')
                else:
                    bundle_id_suffix = bundle_id_suffix.replace('_', '-')
                try:
                    res = urllib.urlopen('%s%s/?t=id' % (settings.CHECK_URL, bundle_id_suffix))
                    rtn = res.read()
                    rtn = json.loads(rtn)
                except Exception, e:
                    raise forms.ValidationError(self.error_msg['server_error'])
                if rtn.get('exist'):
                    raise forms.ValidationError(self.error_msg['exist'] % 'bundle id suffix')
        return bundle_id_suffix


class StudioCloudForm(forms.ModelForm):
    cloud_purpose = forms.CharField(required=False, label=u'Cloud Purpose',
        widget=CustomTextarea)
    studios = forms.ModelMultipleChoiceField(required=False, queryset=None,
        widget=CustomFilteredSelectMultiple('Studios', False,
            {"style": "height: 300px;"}))

    def __init__(self, *args, **kwargs):
        super(StudioCloudForm, self).__init__(*args, **kwargs)
        self.fields['studios'].queryset = Studio.objects.filter(Q(cloud=None) |
            Q(cloud=self.instance))
        self.fields['studios'].initial = Studio.objects.filter(cloud=self.instance)

    def clean_studios(self):
        self.instance.studios = self.cleaned_data.get('studios')
        return self.cleaned_data.get('studios')

    class Meta:
        model = StudioCloud


class StudioAdminForm(forms.ModelForm):

    error_message = {'unique': 'Studio with this code format already exists.'}

    available_store = forms.MultipleChoiceField(required=False,
        widget=CustomCheckboxSelectMultiple, choices=APP_STORE,
        label=u'App Store Availability')

    class Meta:
        model = Studio

    def clean_available_store(self):
        store = self.cleaned_data.get('available_store')
        if not store:
            return ""
        return store

    def clean_ios_code_format(self):
        ios_code_format = self.cleaned_data.get('ios_code_format')
        if ios_code_format:
            if Studio.objects.exclude(id=self.instance.id).filter(
                ios_code_format=ios_code_format).exists():
                raise forms.ValidationError(self.error_message.get('unique'))
        return ios_code_format

    def clean_gp_code_format(self):
        gp_code_format = self.cleaned_data.get('gp_code_format')
        if gp_code_format:
            if Studio.objects.exclude(id=self.instance.id).filter(
                gp_code_format=gp_code_format).exists():
                raise forms.ValidationError(self.error_message.get('unique'))
        return gp_code_format


class AppVersionForm(forms.ModelForm):

    error_message = {'does_not_exists': '%s selected does not exists.',
                     'version_exists': 'version %s already exists'}

    code = forms.CharField(required=True, label='Version Number', max_length=11,
        widget=forms.TextInput(attrs={'style': '''width: 80px;'''}),
        help_text='Just input the number')
    purpose = forms.MultipleChoiceField(required=False, label=u'Production Purpose',
        widget=CustomCheckboxSelectMultiple, choices=PURPOSE)
    owner = forms.ModelChoiceField(required=True, label='Project Coordinator',
        queryset=User.objects.filter(is_active=True, is_staff=True))
#    product_owner = forms.ModelChoiceField(required=True, label='Product Owner',
#        queryset=User.objects.filter(is_active=True, is_staff=True))
    product_owner = forms.MultipleChoiceField(required=True, label='Product Owner',
        widget=FilteredSelectMultiple('Product Owner', False, {'style': 'height: 200px;'}))
    change_list = forms.CharField(required=True, label="What's new in this version",
        widget=CustomTextarea)

    iap_required = forms.ChoiceField(required=True, label='Has IAP?',
        choices=YES_OR_NO)
    ads_required = forms.ChoiceField(required=True, label='Has Ads?',
        choices=YES_OR_NO)
    cross_promo_required = forms.ChoiceField(required=True, label='Has Cross Promo?',
        choices=YES_OR_NO)

    programmer = forms.MultipleChoiceField(required=False, label='Front-end Engineer',
        widget=FilteredSelectMultiple('Front-end Engineer', False, {'style': 'height: 200px;'}))

    sdk_required = forms.ModelMultipleChoiceField(label='SDK in Use',
                                                  required=False,
                                                  queryset=SDKVersion.objects.filter(status='A'),
                                                  widget=FilteredSelectMultiple('SDK Versions',
                                                                                False,
                                                                                {"style": "height: 300px;"}))

    class Meta:
        model = AppVersion

    def __init__(self, *args, **kwargs):
        super(AppVersionForm, self).__init__(*args, **kwargs)
        self.fields['prd_team'].required = True
        choices = (('', '---------'),)
        data = api_call('%s%s' % (settings.TMS_DOMAIN, settings.TMS_GET_STAFFING),
            {'jobfamily': '40,12,20,21'})
        if data.get('code') == 1:
            product_owner = (('', '---------'), ('imported', 'imported'))
            staffs = data['staffs']
            for s in staffs:
                if s['Family_Code'] == '40':
                    programmers = choices + tuple([('%s - %s' % (x['EmployeeCode'], x['ChineseName']),
                                                    '%s - %s' % (x['EmployeeCode'], x['ChineseName']))\
                                                   for x in s['list']])
                if s['Family_Code'] in ['12', '20', '21']:
                    product_owner += tuple([('%s - %s' % (x['EmployeeCode'], x['ChineseName']),
                                             '%s - %s' % (x['EmployeeCode'], x['ChineseName']))\
                                            for x in s['list']])
            self.fields['programmer'].choices = programmers
            self.fields['product_owner'].choices = product_owner
        if self.instance and self.instance.pk:
            self.fields['sdk_required'].queryset = SDKVersion.objects\
                .filter(status='A', sdk_info__platform=self.instance.app.platform)

            self.fields['code'].widget = forms.TextInput(
                attrs={'style': '''width: 80px;''', 'readonly': 'readonly'})
            if self.instance.type == 'N':
                self.fields['purpose'] = forms.CharField(required=False,
                    label='Production Purpose', widget=forms.TextInput(
                        attrs={'readonly': 'readonly'}))
            if self.instance.product_owner:
                initial = self.instance.product_owner.split(',')
                self.initial['product_owner'] = initial
            if self.instance.programmer:
                initial_programmer = self.instance.programmer.split(',')
                self.initial['programmer'] = initial_programmer

    def clean_code(self):
        code = self.cleaned_data.get('code')
        if code and code[0].isalpha():
            code = code[1:]
        if self.instance and self.instance.app:
            if not self.instance.status == 'C':
                if AppVersion.objects.filter(app=self.instance.app, code=code,
                                             status__in=['I', 'S', 'L'])\
                                     .exclude(id=self.instance.pk).exists():
                    raise forms.ValidationError(self.error_message['version_exists'] % code)
        return code

    def clean_owner(self):
        owner = self.cleaned_data.get('owner')
        try:
            user = User.objects.get(username=owner)
        except User.DoesNotExist:
            raise forms.ValidationError(self.error_message['does_not_exists']\
                % 'Project Coordinator')
        return user.pk

    def clean_product_owner(self):
        product_owner = self.cleaned_data.get('product_owner')
        if product_owner:
            product_owner = ','.join(product_owner)
        return product_owner or None

    def clean_purpose(self):
        purpose = self.cleaned_data.get('purpose')
        if not purpose:
            return ""
        return purpose

    def clean_programmer(self):
        programmer = self.cleaned_data.get('programmer')
        return ','.join(programmer) if programmer else ""


class CompanyForm(forms.ModelForm):

    class Meta:
        model = Company


class CustomGroupForm(forms.ModelForm):

    class Meta:
        model = Group

    permissions = forms.ModelMultipleChoiceField(required=False,
        queryset=Permission.objects.all(),
        widget=FilteredSelectMultiple('Permissions', False,
            {"style": "height: 300px;"}))
    company = forms.ModelChoiceField(queryset=Company.objects.all())

    def __init__(self, *args, **kwargs):
        super(CustomGroupForm, self).__init__(*args, **kwargs)
        companygroup = self.instance.companygroup if hasattr(self.instance, 'companygroup') else None
        if companygroup:
            self.initial['company'] = self.instance.companygroup.company.id


class CustomUserGroupForm(forms.ModelForm):

    class Meta:
        model = UserGroup
        exclude = ('clouds', )
#    user = forms.ModelMultipleChoiceField(required=False, label='PJMs',
#        queryset=User.objects.filter(is_active=True, is_staff=True),
#        widget=FilteredSelectMultiple('PJMs', False, {"style": "height: 300px;"}))
#     clouds = forms.ModelMultipleChoiceField(required=False, label='Available Studio Clouds',
#         queryset=StudioCloud.objects.all(),
#         widget=FilteredSelectMultiple('Studio Clouds', False, {"style": "height: 300px;"}))

    studios = forms.ModelMultipleChoiceField(required=False, label='Available Studio',
        queryset=Studio.objects.all(),
        widget=FilteredSelectMultiple('Studios', False, {"style": "height: 300px;"}))


class ProductionTeamForm(forms.ModelForm):

    class Meta:
        model = ProductionTeam
        exclude = ('group', )

    user = forms.ModelMultipleChoiceField(required=False, label='PJMs',
        queryset=User.objects.filter(is_active=True, is_staff=True),
        widget=FilteredSelectMultiple('PJMs', False, {"style": "height: 300px;"}))
    studios = forms.ModelMultipleChoiceField(required=False, label='Available Studios',
        queryset=Studio.objects.all(),
        widget=FilteredSelectMultiple('Studios', False, {"style": "height: 300px;"}))

    class Media:
        js = ('base/js/custom_production_team.js',)
    #
    # def __init__(self, *args, **kwargs):
    #     super(ProductionTeamForm, self).__init__(*args, **kwargs)
    #     self.fields['studios'].queryset = self.instance.group.get_included_studios()\
    #     if self.instance.group else Studio.objects.all()
    #     self.fields['studios'].initial = self.instance.group.get_included_studios()\
    #     if self.instance.group else Studio.objects.none()


class AppleIDForm(forms.ModelForm):

    class Meta:
        model = AppleID

    def clean_itunes_id(self):
        itunes_id = self.cleaned_data.get('itunes_id')
        if itunes_id:
            if AppleID.objects.exclude(id=self.instance.pk).filter(itunes_id=itunes_id).exists():
                raise forms.ValidationError("Apple ID '%s' already exists!" % itunes_id)
        return itunes_id


class FlurryKeyForm(forms.ModelForm):

    class Meta:
        model = FlurryKey

    def clean_key(self):
        key = self.cleaned_data.get('key')
        if key:
            if FlurryKey.objects.exclude(id=self.instance.pk).filter(key=key).exists():
                raise forms.ValidationError("Flurry key '%s' already exists!" % key)
            if not len(key) == 20:
                raise forms.ValidationError("Flurry key must be 20 characters!")
        return key


class GAKeyForm(forms.ModelForm):

    class Meta:
        model = GAKey

    def clean_key(self):
        key = self.cleaned_data.get('key')
        if key:
            if GAKey.objects.exclude(id=self.instance.pk).filter(key=key).exists():
                raise forms.ValidationError("GA Key '%s' already exists!" % key)
        return key

    def clean_app(self):
        app = self.cleaned_data.get('app')
        if app:
            if GAKey.objects.exclude(id=self.instance.pk).filter(app=app).exists():
                raise forms.ValidationError("App '%s' GA Key already exists!" % app.__unicode__())
        return app


class QuantCastKeyForm(forms.ModelForm):

    class Meta:
        model = QuantCastKey

    def clean_key(self):
        key = self.cleaned_data.get('key')
        if key:
            if QuantCastKey.objects.exclude(id=self.instance.pk).filter(key=key).exists():
                raise forms.ValidationError("QuantCast Key '%s' already exists!" % key)
        return key

    def clean_app(self):
        app = self.cleaned_data.get('app')
        if app:
            if QuantCastKey.objects.exclude(id=self.instance.pk).filter(app=app).exists():
                raise forms.ValidationError("App '%s' QuantCast Key already exists!" % app.__unicode__())
        return app
